package com.store.aspect;

import com.alibaba.fastjson.JSON;
import com.store.annotation.OperationLog;
import com.store.domain.entity.Log;
import com.store.domain.entity.User;
import com.store.mapper.UserMapper;
import com.store.service.LogService;
import com.store.utils.HttpContextUtils;
import com.store.utils.IPUtils;
import com.store.utils.ThreadLocalUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Method;
import java.util.Arrays;

import static cn.hutool.extra.servlet.ServletUtil.getClientIP;

/**
 * @author yu
 * @date 2024/6/26
 */
@Aspect
@Component
public class OperationLoaAspect {
    @Resource
    private LogService logService;
    @Resource
    private UserMapper userMapper;
    @Pointcut("@annotation(com.store.annotation.OperationLog)")
    public void operationLogPointCut(){}
    /**
     * 处理请求前执行
     */
    @Around("operationLogPointCut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long time = System.currentTimeMillis() - startTime;
        saveLog(joinPoint, time);
        return result;
    }
    private void saveLog(ProceedingJoinPoint joinPoint, long time){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log log = new Log();
        OperationLog operationLog = method.getAnnotation(OperationLog.class);
        if (operationLog != null){
            //注解的信息
            log.setBusinessName(operationLog.value());
        }
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.setClassPath(className);
        log.setMethodName(methodName);

        //请求参数
        Object[] args = joinPoint.getArgs();
        try {
            String params = Arrays.toString(args);
            log.setParamsJson(params);
        } catch (Exception e){

        }
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        log.setIp(IPUtils.getIpAddr(request));
        //获取用户信息
        Integer userId = ThreadLocalUtil.getLocal();
        User user = userMapper.selectById(userId);
        log.setUsername(user.getUsername());
        log.setRequestUrl(String.valueOf(request.getRequestURL()));
        log.setRequestMethod(request.getMethod());
        String userAgent = request.getHeader("User-Agent");
        String browserName = "";
        String osName = "";
        // 浏览器判断
        if (userAgent.contains("Edge")) {
            browserName = "Microsoft Edge";
        } else if (userAgent.contains("Chrome")) {
            browserName = "Google Chrome";
        } else if (userAgent.contains("Firefox")) {
            browserName = "Mozilla Firefox";
        } else if (userAgent.contains("Safari")) {
            browserName = "Apple Safari";
        } else if (userAgent.contains("Trident") || userAgent.contains("MSIE")) { // IE 11以下版本
            browserName = "Internet Explorer";
        } else {
            browserName = "Other";
        }
        if (userAgent.toLowerCase().contains("windows")) {
            osName = "Windows";
        } else if (userAgent.toLowerCase().contains("mac")) {
            osName = "Mac OS";
        } else if (userAgent.toLowerCase().contains("x11")) {
            osName = "Unix";
        } else if (userAgent.toLowerCase().contains("android")) {
            osName = "Android";
        } else if (userAgent.toLowerCase().contains("iphone") || userAgent.toLowerCase().contains("ipad")) {
            osName = "iOS";
        } else {
            osName = "Other";
        }

        log.setOperationName(osName);
        log.setBrowserName(browserName);
        log.setSpendTime(time);
        logService.save(log);
    }
}
